# 1.导包
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, roc_curve, roc_auc_score  # 因为逻辑回归实际是解决分类问题的，因此准确度依然还可以用
from matplotlib import pyplot as plt

# 2.读取数据
df = pd.read_csv("./breast-cancer-wisconsin.csv",encoding='utf-8')

# 3.数据基本处理

# 3.1填充缺失值（?填充）
df.replace("?", np.NAN, inplace=True)

# 3.2删除空值
df.dropna(inplace=True)

# 3.3 划分数据集
x_data = df.iloc[:, 1:-1]   # 获取到特征值
y_data = df.iloc[:, -1]     # 获取到目标值

# 4.将目标值为2,4 的变成 0,1类别的
"""
    目标值需要调整为{0, 1}或者{-1, 1}
    y_true takes value in {2, 4} and pos_label is not specified: 
    either make y_true take value in {0, 1} or {-1, 1} or pass pos_label explicitly.
"""
y_data = y_data.apply(lambda x: 0 if x == 2 else 1)
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=922)

# 5.特征工程
# 5.1 特征预处理(标准化处理)
transformer = StandardScaler()
x_train = transformer.fit_transform(x_train)

# 6.模型构建
model = LogisticRegression()  # 逻辑回归算法
model.fit(x_train, y_train)

# 7.模型评估
"""
    predict：内部会进行概率值和阈值的比较，直接输出预测的分类类别
    predict_proba：输出正例、反例的概率值，不会直接告诉你预测的分类类别。通过它可以人为设置概率阈值
"""
# 7.1 对测试集进行标准化
x_test = transformer.transform(x_test)
y_predict = model.predict(x_test)           # 根据测试集的特征值 得到 预测值 y_predict

# 7.2 predict_proba 得到分类的概率值
y_predict_proba = model.predict_proba(x_test)   # 输出正例和反例的概率值
print(y_predict_proba)

# result = accuracy_score(y_test, y_predict)
# print(result)
# 7.3 评估
print(f"预测准确度为：{accuracy_score(y_test, y_predict)}")    # 使用真实的目标值和 预测值进行对比

# 7.4 绘制roc曲线
fpr, tpr, thresholds = roc_curve(y_test, y_predict_proba[:, 1])
print(f"fpr={fpr},tpr={tpr},thresholds={thresholds}")
plt.plot(fpr, tpr, c="r")
plt.xlabel("fpr")
plt.ylabel("tpr")
plt.show()

# 7.5 得到AUC的面积
print(f"AUC的面积为：{roc_auc_score(y_test, y_predict_proba[:, 1])}")